#ifndef OBSTACLEMANAGER_H
#define OBSTACLEMANAGER_H

#include "string"
#include "vector"

#include "ngl/Transformation.h"
#include "ngl/TransformStack.h"

#include "StaticObject.h"
#include "ShaderManager.h"


/// @file ObstacleManager.h
/// @brief manages the creation, and drawing of obtacles
/// @author Perseedoss Rajiv
/// @version 1.0
/// @date 29.03.11
/// Revision History :
/// Initial Version 29.03.11
/// @class ObstacleManager
/// @brief manager to create obstacles, draw them and maintain a central list of obstacles

class ObstacleManager
{
public:
    /// @brief ctor
    /// @param[in] _enableObstacle flag to determine if obstacles are enabled
    ObstacleManager(const bool _enableObstacle = false);

    /// @brief dtor
    ~ObstacleManager();

    /// @brief creates vbo for drawing
    void loadGeometry();

    /// @brief draws the obstacles
    /// @param[in] _txStack the transform stack, used for pushing and popping opengl states
    /// @param[in,out] io_sman the shader manager, used for shading/rendering of the objects
    /// @param[in] _shader the shader used for drawing
    void draw
            (
                ngl::TransformStack _txStack,
                ShaderManager* io_sman,
                const std::string _shader
            );

    /// @brief returns the list of obstacles
    inline std::vector<StaticObject*>* getObstacleList() const { return m_obstacleList; }

    /// @brief returns a flag to determine if obstacles are enabled
    inline bool getEnableObstacle() const { return m_enableObstacle; }

    /// @brief set the flag to determine if obstacles are enabled
    /// @param[in] _state the state of the obstacle enablement
    inline void setEnableObstacle(const bool _state) { m_enableObstacle = _state; }

    /// @brief returns the state of whether wireframe drawing is enabled
    inline bool getDrawWireframe() const { return m_drawWireframe; }

    /// @brief set the flag to determine if obstacles are to be drawn in wireframe
    /// @param[in] _state the state of the wireframe enablement
    inline void setDrawWireframe(const bool _state) { m_drawWireframe = _state; }

    /// @brief returns the state of whether the drawing of the influence sphere is enabled
    inline bool getDrawInfluenceSphere() const { return m_drawInfluenceSphere; }

    /// @brief set the flag to determine if the influence sphere of the obstacles are to be drawn
    /// @param[in] _state the state of the draw influence sphere enablement
    inline void setDrawInfluenceSphere(const bool _state) { m_drawInfluenceSphere = _state; }

    /// @brief returns the number of times of influence sphere hit
    inline int getCountOfInfluenceSphereHit() const { return m_countOfInfluenceHit; }

    /// @brief returns the number of times of collisions
    inline int getCountOfCollisions() const { return m_countOfBoundingHit; }

    /// @brief increments the counter of influence sphere hit
    inline void incrementInfluenceSphereHit() { ++m_countOfInfluenceHit; }

    /// @brief increments the counter of collision
    inline void incrementBoundingSphereHit() { ++m_countOfBoundingHit; }

    /// @brief clears the stats counters
    inline void clearStatCounters() { m_countOfBoundingHit = 0; m_countOfInfluenceHit = 0; }


private:
    /// @brief the list of obstacles
    std::vector<StaticObject*>* m_obstacleList;

    /// @brief flag to determine whether obstacle is enabled
    bool m_enableObstacle;

    /// @brief flag to determine whether wireframe drawing is enabled
    bool m_drawWireframe;

    /// @brief flag to determine whether the drawing of the influence sphere of obstacles is enabled
    bool m_drawInfluenceSphere;

    /// @brief counter for number of times an object is inside the influence sphere of obstacles
    int m_countOfInfluenceHit;

    /// @brief counter for number of times an object collides with obstacles
    int m_countOfBoundingHit;

};

#endif // OBSTACLEMANAGER_H
